//
// Copyright (c) 2005 BroadVision, Inc. All rights reserved.
//
// This software is copyrighted.  Under the copyright laws, this software
// may not be copied, in whole or in part, without prior written consent
// of BroadVision, Inc. or its assignees.  This software is provided under
// the terms of a license between BroadVision and the recipient, and its
// use is subject to the terms of that license.
//
// This software may be protected by one or more U.S. and International
// patents.  Certain applications of BroadVision One-To-One software are
// covered by U.S. patent 5,710,887.
//
// TRADEMARKS: BroadVision and BroadVision One-To-One are registered
// trademarks of BroadVision, Inc., in the United States and the European
// Community, and are trademarks of BroadVision, Inc., in other
// countries.  The BroadVision logo, is a trademark of BroadVision, Inc.,
// in the United States and other countries. Additionally, IONA and Orbix
// are trademarks of IONA Technologies, Ltd.  RSA, MD5, and RC2 are
// trademarks of RSA Data Security, Inc.
//

package com.broadvision.manage.common.tools.user;

import java.security.Principal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.beanutils.BasicDynaClass;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaProperty;

import com.broadvision.data.common.DataAttribute;
import com.broadvision.data.common.DataAttributeList;
import com.broadvision.data.common.DataType;
import com.broadvision.data.common.PrimitiveType;
import com.broadvision.lictool2.LicToolWebApp;
import com.broadvision.system.accesscontrol.client.AccessManager;
import com.broadvision.system.accesscontrol.client.GenericRoleDB;
import com.broadvision.system.accesscontrol.client.GenericSectionDB;
import com.broadvision.system.accesscontrol.client.RoleType;
import com.broadvision.system.accesscontrol.client.ServiceObjectInfo;
import com.broadvision.system.accesscontrol.client.UserRole;
import com.broadvision.system.accesscontrol.utils.ServiceRoleFilter;
import com.broadvision.visitor.authentication.AuthenticationConstants;
import com.broadvision.visitor.client.Visitor;
import com.broadvision.visitor.client.VisitorGroupManager;
import com.broadvision.visitor.client.VisitorManager;
import com.broadvision.visitor.exceptions.VisitorProfileException;
import com.broadvision.visitor.interfaces.VisitorGroup;
import com.broadvision.web.util.BasicDynaBean;
import com.broadvision.web.util.DateTime;
import com.dps.broadvision.visitor.client.ExternalVisitorManager;


/**
 * Provides business logic methods for viewing, updating user.
 */
public class UserProfile {

  public static String USER_ADMIN = "UserAdmin";
  public static String PROCESS_ADMIN = "ProcessAdmin";
  public static String PACK_DEPLOYER = "PackageDeployer";
  public static String PROCESS_MODELER = "ProcessModeler";
  public static String PERSONALIZATION_ADMIN = "PersonalizationAdmin";
  public static String NAVIGATION_ADMIN = "NavigationAdmin";
  public static String SERVICE_ADMIN = "ServiceAdministrator";
  public static String CONTENT_ADMIN = "ContentAdmin";
  public static String CONTENT_PUBLISHER = "ContentPublisher";
  public static String ORGANIZATION_ADMIN = "OrganizationAdmin";
  public static String CHANNEL_ADMIN = "ChannelAdmin";
  public static String MICROSITE_CREATOR = "MicrositeCreator";
  public static String STAGING_MANAGER = "StagingManager";
  public static String STAGING_SHIPPER = "StagingShipper";
  public static String STAGING_RECIPIENT = "StagingRecipient";
  public static String COMMERCE_ADMIN = "CommerceAdmin";
  
  public static long UNDEFINED_USER_ID = -1;

  private long userId = UNDEFINED_USER_ID;
  private String userAlias;
  private String password;
  private String confirmPassword;
  private String firstName;
  private String middleName;
  private String lastName;
  private String fullName;
  private String address1;
  private String address2;
  private String mailStop;
  private String city;
  private String state;
  private String zipCode;
  private String country;
  private String phone; // business phone
  private String fax;
  private String email;
  private String[] assignedRoles = {};
  private boolean canEditRole;
  private boolean emailAlert;
  private boolean inboxAlert;
  private boolean isPmOnly;
  private boolean updateRole = true;

  private long serviceId = 0;
  private String[] groupFQNs = {};


  // portal attributes
  private boolean kmUserDeleted;

  private long userTemplateId;
  private boolean kmEmailAlert;

  private Visitor visitor = null;
  private DynaBean dynaBean = null;
  // private HashMap mapBasicDynaClass = null;
  private static final String defaultPassword = "abcdef";
  private static final String defaultConfirmPassword = "uvwxyz";


 /**
  * Default constructor
  */
  public UserProfile() {
  }

  public UserProfile(long userId) {
    setUserId(userId);
  }

  /**
   * Retrieves visitor attribute data for viewing purposes
   */
  public void view() throws VisitorProfileException {
    visitor = getVisitor();
    setUserAlias(visitor.getUserAlias());
    setAttributes(visitor);
    setAssignedRoles(getRolesForVisitor(visitor, true));
  }    

  /**
   * Retrieves visitor attributes for editting purpose
   */
  public void edit() throws VisitorProfileException {
    visitor = getVisitor();
    setPassword(defaultPassword);
    setConfirmPassword(defaultConfirmPassword);
    setUserAlias(visitor.getUserAlias());
    setAttributes(visitor);
    // TODO: find this canEditRole
    boolean canEditRole = true;
    if (canEditRole) {
      setAssignedRoles(getRolesForVisitor(visitor, false));
    }
    else {
    }
  }        

  /**
   * Saves visitor attributes into databases
   */
  public void save() throws VisitorProfileException {
    if (getUserId() == UNDEFINED_USER_ID) {
      create();
    }
    else {
      update();
    }
  } 

  /**
   * Creates a visitor by saving visitor attributes into database
   */
  public void create() throws VisitorProfileException {
	System.out.println("Entering in "+this.getClass());
	
	//VisitorManager visitorMgr = new VisitorManager();
    //visitor = visitorMgr.createExternalVisitor(getUserAlias(), getPassword());
	System.out.println("Going to create User using OidVisitorManager"+this.getClass());
	ExternalVisitorManager externalVisitorManager = new ExternalVisitorManager();
	visitor=externalVisitorManager.createNewVisitor(getUserAlias(),getPassword());
    try
    {
    	/*
    	 * Saving userId in LDAP
    	 * 29 October 2008
    	 * Author:Ahmad Shakil
    	*/
    	if(visitor!=null){
    		System.out.println("User created :"+getUserAlias());
    		System.out.println("Going to update user id in LDAP");
        	visitor.setStringValue("ACCOUNT_ID_LDAP", ""+visitor.getId());
        	visitor.save();
        	System.out.println("visitor.save() exited without exception");
    	}
    	else
    	{
    		System.out.println("visitor object is null.Failed to create User : "+getUserAlias());
    	}
    	
    }
    catch(Exception exc){
    	System.out.println("Failed to save user Id in LDAP : "+exc.getMessage());
    	exc.printStackTrace();
    }
    // check config to determine which name fields to use.
    if (VisitorManager.isUsingFMLName()) {
      visitor.setStringValue("FIRST_NAME", getFirstName());
      visitor.setStringValue("MIDDLE_NAME", getMiddleName());
      visitor.setStringValue("LAST_NAME", getLastName());
    }
    else {
      visitor.setStringValue("NAME", getFullName());
    }
    getAttributes(visitor);
    // Users created from PMC always get this flag set to true.
    // That way we know we created it from PMC.
    //visitor.setIntValue("IS_PM_ONLY", 1);
    visitor.save();
 
    // set roles 
    try {
      AccessManager accessMgr = AccessManager.instance();
      String[] assignedRoles = getAssignedRoles();
      for (int i = 0; i < assignedRoles.length; i++) {
        accessMgr.grantRole(visitor, assignedRoles[i]);
      }
    }
    catch (Exception e) {
      // TODO: do something about these exceptions
      // quietly return for now
    }
    // save group membership
    if ((null != groupFQNs) && (groupFQNs.length > 0)) {
      try {
        List visitors = new ArrayList(1);
        visitors.add(visitor);
        for (int i = 0; i < groupFQNs.length; i++) {
          VisitorGroup thisGroup = VisitorGroupManager.getVisitorGroupByFqn(groupFQNs[i]);
          thisGroup.addVisitors(visitors);
        }
      }
      catch (Exception e) {
        // TODO: do something about these exceptions
        // quietly return for now
      }
    }
    setUserId(visitor.getId());
  }
    
  /**
   * Updates the attributes of a visitor.
   */
  public void update() throws VisitorProfileException {
    visitor = getVisitor();
    if (!getPassword().equals(defaultPassword) || !getConfirmPassword().equals(defaultConfirmPassword)) {
      try {
        HashMap userCredentials = new HashMap();
        userCredentials.put(AuthenticationConstants.PASSWORD, getPassword());
        visitor.modifyExternalPassword(userCredentials);
      } 
      catch (Exception ex) {
        // TODO: log it
        // ex.printStackTrace();
      }
    }
    // check config to determine which name fields to use.
    if (VisitorManager.isUsingFMLName()) {
      visitor.setStringValue("FIRST_NAME", getFirstName());
      visitor.setStringValue("MIDDLE_NAME", getMiddleName());
      visitor.setStringValue("LAST_NAME", getLastName());
    }
    else {
      visitor.setStringValue("NAME", getFullName());
    }
    getAttributes(visitor);
    visitor.save();
    if (updateRole) {
      // update roles
      updateRole();
    }
    setUserId(visitor.getId());
  }

  public void updateRole() {
    // update roles
    try {
      AccessManager accessMgr = AccessManager.instance();
      String[] listOfOldRoles = getRolesForVisitor(visitor, false);
      ServiceObjectInfo sIO = new ServiceObjectInfo(serviceId);
      if (listOfOldRoles != null) {
        for (int i = 0; i < listOfOldRoles.length; i++) {
          String roleName = listOfOldRoles[i];
          if (roleName.equals(SERVICE_ADMIN)) {
            accessMgr.revokeRole(visitor, SERVICE_ADMIN, sIO);
          }
          else if (roleName.equals(NAVIGATION_ADMIN)) {
            accessMgr.revokeRole(visitor, NAVIGATION_ADMIN, sIO);
          }
          else if (roleName.equals(PERSONALIZATION_ADMIN)) {
            accessMgr.revokeRole(visitor, PERSONALIZATION_ADMIN, sIO);
          }
          else if (roleName.equals(MICROSITE_CREATOR)) {
            accessMgr.revokeRole(visitor, MICROSITE_CREATOR, sIO);
          }
          else if (roleName.equals(CONTENT_PUBLISHER)) {
            accessMgr.revokeRole(visitor, CONTENT_PUBLISHER, sIO);
          }
          else if (roleName.equals(USER_ADMIN) || roleName.equals(PROCESS_ADMIN) || roleName.equals(PACK_DEPLOYER) ||
              roleName.equals(PROCESS_MODELER) || roleName.equals(CONTENT_ADMIN) || roleName.equals(STAGING_MANAGER) ||
              roleName.equals(STAGING_SHIPPER) || roleName.equals(STAGING_RECIPIENT) || roleName.equals(COMMERCE_ADMIN) ) {
            if (!"bvadmin".equals(visitor.getUserAlias()) || !roleName.equals(USER_ADMIN)) {
              accessMgr.revokeRole(visitor, roleName);
            }
          }
        }
      }
      String[] assignedRoles = getAssignedRoles();
      for (int i = 0; i < assignedRoles.length; i++) {
        String roleName = assignedRoles[i];
        if (roleName.equals(USER_ADMIN) || roleName.equals(PROCESS_ADMIN) || roleName.equals(PROCESS_MODELER) || 
            roleName.equals(PACK_DEPLOYER) || roleName.equals(CONTENT_ADMIN) || roleName.equals(STAGING_MANAGER) ||
            roleName.equals(STAGING_SHIPPER) || roleName.equals(STAGING_RECIPIENT) || roleName.equals(COMMERCE_ADMIN) ) {
          accessMgr.grantRole(visitor, assignedRoles[i]);
        } 
        else if (roleName.equals(SERVICE_ADMIN)) {
          accessMgr.grantRole(visitor, SERVICE_ADMIN, sIO);
        }
        else if (roleName.equals(NAVIGATION_ADMIN)) {
          accessMgr.grantRole(visitor, NAVIGATION_ADMIN, sIO);
        }
        else if (roleName.equals(PERSONALIZATION_ADMIN)) {
          accessMgr.grantRole(visitor, PERSONALIZATION_ADMIN, sIO);
        }
        else if (roleName.equals(CONTENT_PUBLISHER)) {
          accessMgr.grantRole(visitor, CONTENT_PUBLISHER, sIO);
        }
        else if (roleName.equals(ORGANIZATION_ADMIN)) {
          //accessMgr.grantRole(visitor, "PersonalizationAdmin", org2);
        }
        else if (roleName.equals(CHANNEL_ADMIN)) {
          //accessMgr.grantRole(visitor, "PersonalizationAdmin", org2);
        }
        else if (roleName.equals(MICROSITE_CREATOR)) {
          accessMgr.grantRole(visitor, MICROSITE_CREATOR, sIO);
        }
      }
    }
    catch (Exception e) {
      e.printStackTrace();
      // TODO: do something about these exceptions
      // quietly return for now
    }
  }

  /**
   * Deletes a user, which is actually putting the user state to be inactive
   */
  public void delete() throws VisitorProfileException  {
    setAssignedRoles(getRolesForVisitor(getVisitor(), false));
    // remove roles 
    try {
      AccessManager accessMgr = AccessManager.instance();
      String[] assignedRoles = getAssignedRoles();
      for (int i = 0; i < assignedRoles.length; i++) {
        if (!"bvadmin".equals(visitor.getUserAlias())) {
          accessMgr.revokeRole(visitor, assignedRoles[i]);
        }
      }
    }
    catch (Exception e) {
      // TODO: do something about these exceptions
      // quietly return for now
      //e.printStackTrace();
    }
    VisitorManager visitorMgr = new VisitorManager();
    //visitorMgr.deactivateVisitor(getUserAlias());
    visitorMgr.invalidateVisitor(getUserAlias()); 
  }

  public Visitor getVisitor() throws VisitorProfileException {
    if (visitor == null) {
      VisitorManager visitorManager = new VisitorManager();
      visitor = visitorManager.getVisitor(getUserId());
    }
    return visitor;
  }
  
  /*
  public List getDynaBeansForMultiValueAttr(String mvTable) {
    ArrayList dbList = new ArrayList();
    BasicDynaClass bdc = this.getBasicDynaClassForMultiValueAttr(mvTable);
    if (bdc == null) {
      return dbList;
    }
    TableData td = null;
    try {
      td = this.getVisitor().getListData(mvTable);
    }
    catch (Exception ex) {
      ;
    }
    if (td == null) {
      return dbList;
    }
    for (int i = 0; i < td.size(); i++) {
      DynaBean db = null;
      try {
        db = bdc.newInstance();
      }
      catch (Exception ex) {
        break;
      }
      dbList.add(db);
      RowData rd = td.getRow(i);
      DynaProperty[] properties = bdc.getDynaProperties();
      for (int j = 0; j < properties.length; j++) {
        String propName = properties[j].getName();
        if (properties[j].getType() == String.class) {
          db.set(propName, rd.getStringValue(propName));
        }
        else if (properties[j].getType() == Long.class) {
          db.set(propName, new Long(rd.getLongValue(propName)));
        }
        else if (properties[j].getType() == Integer.class) {
          db.set(propName, new Integer(rd.getIntValue(propName)));
        }
        else if (properties[j].getType() == Double.class) {
          db.set(propName, new Double(rd.getDoubleValue(propName)));
        }
        else if (properties[j].getType() == Date.class) {
          db.set(propName, rd.getDateTimeValue(propName));
        }
        else if (properties[j].getType() == Boolean.class) {
          db.set(propName, 
              rd.getIntValue(propName) == 1 ? Boolean.TRUE : Boolean.FALSE);
        }
      }
    }
    return dbList;
  }

  public BasicDynaClass getBasicDynaClassForMultiValueAttr(String mvTable) {
    if (this.mapBasicDynaClass != null && this.mapBasicDynaClass.get(mvTable) != null) {
      return (BasicDynaClass)this.mapBasicDynaClass.get(mvTable);
    }
    VisitorManager vmgr = new VisitorManager();
    DataAttributeList attList = null;
    try {
      attList = vmgr.getProfileMultiValueInfo(mvTable);
    }
    catch (Exception ex) {
      ;
    }
    if (attList == null || attList.size() <= 0) {
      return null;
    }
    int size = attList.size();
    DynaProperty[] properties = new DynaProperty[size];
    for (int i = 0; i < attList.size(); i++) {
      DataAttribute oneAtt = (DataAttribute)attList.get(i);
      String attName = oneAtt.getName();
      DataType attDataType = oneAtt.getType();
      if (attDataType.isCustomType()) {
        attDataType = attDataType.getBaseType();
      }
      PrimitiveType attPT = attDataType.getPrimitiveType();
      Class theClass = String.class;
      if (attPT.equals(PrimitiveType.BooleanType)) {
        theClass = Boolean.class;
      }
      else if (attPT.equals(PrimitiveType.ByteArrayType)) {
        theClass = String.class;
      }
      else if (attPT.equals(PrimitiveType.ClobType)) {
        theClass = String.class;
      }
      else if (attPT.equals(PrimitiveType.DateTimeType)) {
        theClass = Date.class;
      }
      else if (attPT.equals(PrimitiveType.DictType)) {
        theClass = Integer.class;
      }
      else if (attPT.equals(PrimitiveType.DoubleType)) {
        theClass = Double.class;
      }
      else if (attPT.equals(PrimitiveType.EnumType)) {
        theClass = Integer.class;
      }
      else if (attPT.equals(PrimitiveType.IntType)) {
        theClass = Integer.class;
      }
      else if (attPT.equals(PrimitiveType.LongType)) {
        theClass = Long.class;
      }
      else if (attPT.equals(PrimitiveType.MoneyType)) {
        theClass = Double.class;
      }
      else if (attPT.equals(PrimitiveType.OIDType)) {
        theClass = Long.class;
      }
      else if (attPT.equals(PrimitiveType.StringType)) {
        theClass = String.class;
      }
      else if (attPT.equals(PrimitiveType.TextType)) {
        theClass = String.class;
      }
      properties[i] = new DynaProperty(attName, theClass);
    }
    BasicDynaClass bdc = new BasicDynaClass("epBasicDynaClass" + mvTable, BasicDynaBean.class, properties);
    this.mapBasicDynaClass.put(mvTable, bdc);
    return bdc;
  }
  */
  
  public DynaBean getDynaBean() {
    if (this.dynaBean != null) {
      return this.dynaBean;
    }
    DataAttributeList attList = null;
    DynaProperty[] properties = null;
    try {
      attList = getVisitor().getAttributes();
    }
    catch (Exception ex) {
      ;
    }
    if (attList != null) {
      int size = attList.size();
      properties = new DynaProperty[size];
      for (int i = 0; i < size; i++) {
        DataAttribute oneAtt = attList.get(i);
        String attName = oneAtt.getName();
        DataType attDataType = oneAtt.getType();
        if (attDataType.isCustomType()) {
          attDataType = attDataType.getBaseType();
        }
        PrimitiveType attPT = attDataType.getPrimitiveType();
        Class theClass = String.class;
        if (attPT.equals(PrimitiveType.BooleanType)) {
          theClass = Boolean.class;
        }
        else if (attPT.equals(PrimitiveType.ByteArrayType)) {
          theClass = String.class;
        }
        else if (attPT.equals(PrimitiveType.ClobType)) {
          theClass = String.class;
        }
        else if (attPT.equals(PrimitiveType.DateTimeType)) {
          theClass = DateTime.class;
        }
        else if (attPT.equals(PrimitiveType.DictType)) {
          theClass = Integer.class;
        }
        else if (attPT.equals(PrimitiveType.DoubleType)) {
          theClass = Double.class;
        }
        else if (attPT.equals(PrimitiveType.EnumType)) {
          theClass = Integer.class;
        }
        else if (attPT.equals(PrimitiveType.IntType)) {
          theClass = Integer.class;
        }
        else if (attPT.equals(PrimitiveType.LongType)) {
          theClass = Long.class;
        }
        else if (attPT.equals(PrimitiveType.MoneyType)) {
          theClass = Double.class;
        }
        else if (attPT.equals(PrimitiveType.OIDType)) {
          theClass = Long.class;
        }
        else if (attPT.equals(PrimitiveType.StringType)) {
          theClass = String.class;
        }
        else if (attPT.equals(PrimitiveType.TextType)) {
          theClass = String.class;
        }
        properties[i] = new DynaProperty(attName, theClass);
      }
    }
    if (properties != null) {
      BasicDynaClass dynaClass = new BasicDynaClass("epBasicDynaClass", 
          BasicDynaBean.class, properties);
      try {
        this.dynaBean = dynaClass.newInstance();
      }
      catch (Exception ex) {
        ;
      }
    }
    return this.dynaBean;
  }
  
  /**
   * Helper method to get attributes for a visitor for create() and update()
   */
  private void getAttributes(Visitor visitor) {
    visitor.setStringValue("ADDRESS", getAddress1());
    visitor.setStringValue("ADDRESS_2", getAddress2());
    visitor.setStringValue("MAIL_STOP", getMailStop());
    visitor.setStringValue("CITY", getCity());
    visitor.setStringValue("STATE", getState());
    visitor.setStringValue("ZIP", getZipCode());
    visitor.setStringValue("COUNTRY", getCountry());
    visitor.setStringValue("BUS_PHONE", getPhone());
    visitor.setStringValue("FAX", getFax());
    visitor.setStringValue("EMAIL", getEmail());
    visitor.setIntValue("PM_EMAIL_ALERT", ((getEmailAlert() == true) ? 1 : 0));
    visitor.setIntValue("PM_INBOX_ALERT", ((getInboxAlert() == true) ? 1 : 0));
    // this negat is needed since we show the user as active == not deleted
    visitor.setIntValue("KM_USER_DELETED", (getKmUserDeleted() ? 1 : 0));
    //visitor.setLongValue("KM_USERTYPE_ID", getUserTemplateId());
    //visitor.setIntValue("KM_EMAIL_ALERT", ((getKmEmailAlert() == true) ? 1 : 0));
    DynaBean theBean = this.getDynaBean();
    if (theBean != null) {
      DynaProperty[] properties = theBean.getDynaClass().getDynaProperties();
      for (int i = 0; i < properties.length; i++) {
        String propName = properties[i].getName();
        Object theObject = theBean.get(propName);
        if (theObject == null) {
          continue;
        }
        if (properties[i].getType() == String.class) {
          visitor.setStringValue(propName, (String)theObject);
        }
        else if (properties[i].getType() == Long.class) {
          visitor.setLongValue(propName, ((Long)theObject).longValue());
        }
        else if (properties[i].getType() == Integer.class) {
          visitor.setIntValue(propName, ((Integer)theObject).intValue());
        }
        else if (properties[i].getType() == Double.class) {
          visitor.setDoubleValue(propName, ((Double)theObject).doubleValue());
        }
        else if (properties[i].getType() == DateTime.class) {
          DateTime dateTime = (DateTime)theObject;
          visitor.setDateTimeValue(propName, dateTime.getDate());
        }
        else if (properties[i].getType() == Boolean.class) {
          visitor.setIntValue(propName, 
              ((Boolean)theObject).booleanValue() ? 1 : 0);
        }
      }
    }
  }

  /**
   * Helper method to set visitor profile attribute for viwe() and edit()
   */
  private void setAttributes(Visitor visitor) {
    String[] attrNames = {"FIRST_NAME", "MIDDLE_NAME", "LAST_NAME", "NAME",
        "ADDRESS", "ADDRESS_2", "MAIL_STOP", 
			  "CITY", "STATE", "ZIP", "COUNTRY", "BUS_PHONE",
			  "FAX", "EMAIL", "IS_PM_ONLY", "KM_USER_DELETED"};
    try {
      visitor.getValues(attrNames, true);
    }
    catch (Exception ex) {
    }
    // check config to determine which name fields to use.
    if (VisitorManager.isUsingFMLName()) {
      setFirstName(visitor.getStringValue("FIRST_NAME"));
      setMiddleName(visitor.getStringValue("MIDDLE_NAME"));
      setLastName(visitor.getStringValue("LAST_NAME"));
    }
    else {
      setFullName(visitor.getStringValue("NAME"));
    }
    setAddress1(visitor.getStringValue("ADDRESS"));
    setAddress2(visitor.getStringValue("ADDRESS_2"));
    setMailStop(visitor.getStringValue("MAIL_STOP"));
    setCity(visitor.getStringValue("CITY"));
    setState(visitor.getStringValue("STATE"));
    setZipCode(visitor.getStringValue("ZIP"));
    setCountry(visitor.getStringValue("COUNTRY"));
    setPhone(visitor.getStringValue("BUS_PHONE"));
    setFax(visitor.getStringValue("FAX"));
    setEmail(visitor.getStringValue("EMAIL"));
    setEmailAlert((visitor.getIntValue("PM_EMAIL_ALERT") == 1));
    setInboxAlert((visitor.getIntValue("PM_INBOX_ALERT") == 1));
    setIsPmOnly((visitor.getIntValue("IS_PM_ONLY") == 1));
    // this negat is needed since we show the user as active == not deleted
    setKmUserDeleted((visitor.getIntValue("KM_USER_DELETED") == 1));
    //setUserTemplateId(visitor.getLongValue("KM_USERTYPE_ID"));
    //setKmEmailAlert((visitor.getIntValue("KM_EMAIL_ALERT") == 1));
    DynaBean theBean = this.getDynaBean();
    if (theBean != null) {
      DynaProperty[] properties = theBean.getDynaClass().getDynaProperties();
      for (int i = 0; i < properties.length; i++) {
        String propName = properties[i].getName();
        if (properties[i].getType() == String.class) {
          theBean.set(propName, visitor.getStringValue(propName));
        }
        else if (properties[i].getType() == Long.class) {
          theBean.set(propName, new Long(visitor.getLongValue(propName)));
        }
        else if (properties[i].getType() == Integer.class) {
          theBean.set(propName, new Integer(visitor.getIntValue(propName)));
        }
        else if (properties[i].getType() == Double.class) {
          theBean.set(propName, new Double(visitor.getDoubleValue(propName)));
        }
        else if (properties[i].getType() == DateTime.class) {
          DateTime dateTime = new DateTime();
          dateTime.setDateTime(visitor.getDateTimeValue(propName));
          theBean.set(propName, dateTime);
        }
        else if (properties[i].getType() == Boolean.class) {
          theBean.set(propName, 
              visitor.getIntValue(propName) == 1 ? Boolean.TRUE : Boolean.FALSE);
        }
      }
    }
  } 

  /**
   * Helper method to get a visitor's role
   */
  private String[] getRolesForVisitor(Visitor visitor, boolean forView)
  {
    List thisUserRoles = new ArrayList();
    try {
      GenericRoleDB genericRoleDB = new GenericRoleDB();
      GenericSectionDB genericSectionDB = new GenericSectionDB();
      ServiceObjectInfo sOI = new ServiceObjectInfo(getServiceId());
      List allGrantedRoles = new ArrayList();
      int portalInstalled = LicToolWebApp.getInstance().checkTag("portal.framework"); 
      List topLevelRoles = genericRoleDB.getGrantedRolesForPrincipal((Principal)visitor, "/Global");
      List portalRoles = null;
      if (portalInstalled >= 0) {
        portalRoles = genericRoleDB.getGrantedRolesForPrincipal((Principal)visitor, "/Global/Portal");
      }
      List p15nRoles = null;
      if (portalInstalled >= 0) {
        p15nRoles = genericRoleDB.getGrantedRolesForPrincipal((Principal)visitor, "/Global/Personalization");
      }
      List contentRoles = genericRoleDB.getGrantedRolesForPrincipal((Principal)visitor, "/Global/ContentManagement");
      List pmcRoles = genericRoleDB.getGrantedRolesForPrincipal((Principal)visitor, "/Global/ProcessManagementCenter");
      List stagingRoles = null;
      int isStagingServices =  LicToolWebApp.getInstance().checkTag("staging.services");
      boolean hasStagingServices = genericSectionDB.sectionExists("StagingServices",
          genericSectionDB.getSection("/Global").getOid());
      if (isStagingServices >= 0 && hasStagingServices == true) {
        stagingRoles = genericRoleDB.getGrantedRolesForPrincipal((Principal)visitor, "/Global/StagingServices");
      }
      
      List commerceRoles = null;
      int isCommerce =  LicToolWebApp.getInstance().checkTag("commerce.shopping");
      boolean hasCommerce = genericSectionDB.sectionExists("Commerce",
          genericSectionDB.getSection("/Global").getOid());
      if (isCommerce >= 0 && hasCommerce == true) {
        commerceRoles = genericRoleDB.getGrantedRolesForPrincipal((Principal)visitor, "/Global/Commerce");
      }
      
      allGrantedRoles.addAll(topLevelRoles);
      if (portalRoles != null) {
        allGrantedRoles.addAll(portalRoles);
      }
      if (p15nRoles != null) {
        allGrantedRoles.addAll(p15nRoles);
      }
      allGrantedRoles.addAll(contentRoles);
      allGrantedRoles.addAll(pmcRoles);
      if (stagingRoles != null) {
        allGrantedRoles.addAll(stagingRoles);
      }
      if (commerceRoles != null) {
        allGrantedRoles.addAll(commerceRoles);
      }
      int i = 0;
      for (Iterator it = allGrantedRoles.iterator(); it.hasNext(); ) {
        Object object = it.next();
        if (object instanceof UserRole) {
          UserRole userRole = (UserRole) object;
          if (ServiceRoleFilter.isServiceRole(userRole)) {
             if (! ServiceRoleFilter.isUserPermittedServiceRole(visitor, userRole, sOI) ) {
                continue;
             }
          }
          if (forView) {
            thisUserRoles.add(userRole.getFriendlyName());
          }
          else {
            thisUserRoles.add(userRole.getName());
          }
        }
      }
      AccessManager accessMgr = AccessManager.instance();
      if (accessMgr.isUserInRole(visitor, MICROSITE_CREATOR, sOI)) {
        UserRole userRole = genericRoleDB.getUserRole(MICROSITE_CREATOR);
        if (forView) {
          thisUserRoles.add(userRole.getFriendlyName());
        }
        else {
          thisUserRoles.add(userRole.getName());
        }
      }
    }
    catch (Exception ee) {
      // TODO: do something about these exceptions
    }
    String[] pattern = new String[thisUserRoles.size()];
    return ((String[]) thisUserRoles.toArray(pattern));
  }

  public static List getAllRoles(boolean global) {
    List allRoles = new ArrayList();
    try {
      GenericRoleDB genericRoleDB = new GenericRoleDB();
      GenericSectionDB genericSectionDB = new GenericSectionDB();
      int portalInstalled = LicToolWebApp.getInstance().checkTag("portal.framework");
      List topLevelRoles = genericSectionDB.getRolesInSection("/Global");
      for (Iterator it = topLevelRoles.iterator(); it.hasNext();) {
        UserRole userRole = (UserRole) it.next();
        String roleName = userRole.getName();
        if (!(roleName.equals("SiteAdmin") || roleName.equals("AnonymousUser") ||  roleName.equals("ServiceAdmin") ||
            roleName.equals("RegisteredUser") || roleName.equals("Owner"))) {
          if (global) {
            if (RoleType.GLOBAL == userRole.getRoleType()) {
              allRoles.add(userRole);
            }
          }
          else {
            allRoles.add(userRole);
          }
        }
      }    
      if (portalInstalled >= 0) {
        List portalRoles = genericSectionDB.getRolesInSection("/Global/Portal");
        for (Iterator it = portalRoles.iterator(); it.hasNext();) {
          UserRole userRole = (UserRole) it.next();
          if (global) {
            if (RoleType.GLOBAL == userRole.getRoleType()) {
              allRoles.add(userRole);
            }
          }
          else {
            allRoles.add(userRole);
          }
        }
      }
      if (portalInstalled >= 0) {
        List p15nRoles = genericSectionDB.getRolesInSection("/Global/Personalization");
        for (Iterator it = p15nRoles.iterator(); it.hasNext();) {
          UserRole userRole = (UserRole) it.next();
          if (global) {
            if (RoleType.GLOBAL == userRole.getRoleType()) {
              allRoles.add(userRole);
            }
          }
          else {
            allRoles.add(userRole);
          }
        }
      }
      List cntRoles = genericSectionDB.getRolesInSection("/Global/ContentManagement");
      for (Iterator it = cntRoles.iterator(); it.hasNext();) {
        UserRole userRole = (UserRole) it.next();
        if (global) {
          if (RoleType.GLOBAL == userRole.getRoleType()) {
            allRoles.add(userRole);
          }
        }
        else {
          allRoles.add(userRole);
        }
      }      
      List pmcRoles = genericSectionDB.getRolesInSection("/Global/ProcessManagementCenter");
      for (Iterator it = pmcRoles.iterator(); it.hasNext();) {
        UserRole userRole = (UserRole) it.next();
        if (RoleType.GLOBAL == userRole.getRoleType()) {
          allRoles.add(userRole);
        }
      }  
      int isStagingServices =  LicToolWebApp.getInstance().checkTag("staging.services");
      if (isStagingServices >= 0) {
        List stagingRoles = genericSectionDB.getRolesInSection("/Global/StagingServices");
        for (Iterator it = stagingRoles.iterator(); it.hasNext();) {
          UserRole userRole = (UserRole) it.next();
          if (RoleType.GLOBAL == userRole.getRoleType()) {
            allRoles.add(userRole);
          }
        }
      }
      
      int isCommerce =  LicToolWebApp.getInstance().checkTag("commerce.shopping");
      if (isCommerce >= 0) {
        List commerceRoles = genericSectionDB.getRolesInSection("/Global/Commerce");
        for (Iterator it = commerceRoles.iterator(); it.hasNext();) {
          UserRole userRole = (UserRole) it.next();
          if (RoleType.GLOBAL == userRole.getRoleType()) {
            allRoles.add(userRole);
          }
        }
      }
    }
    catch (Exception exx) {
      // do something about these exceptions
    }
    return allRoles;
  }

  /**
   * Provides an access control method.
   * TODO: this may need to be refined to better use the access control
   * framework.
   */
  public static boolean isPermitted(Visitor mgrVisitor, String action) {
    // for testing
    // return true;
    if (null == action) {
      return false;
    }
    if (action.equalsIgnoreCase("view")) {
      return true;
    }
    try {
      AccessManager accessMgr = AccessManager.instance();
      boolean hasUserAdminRole = accessMgr.isUserInRole(mgrVisitor, USER_ADMIN);
      if (hasUserAdminRole) {
        return true;
      }
      if (isOrganizationAdmin(mgrVisitor)) {
        return true;
      }
    }
    catch (Exception ex) {
      // TODO: need to...
    }
    return false;
  }

  /**
   * Tests whether this user is an organization admin
   */
  public boolean isOrganizationAdmin() {
    try {
      return isOrganizationAdmin(getVisitor());
    }
    catch (Exception ex) {
    }
    return false;
  }

  /**
   * Tests whether this user is an organization admin
   */
  public static boolean isOrganizationAdmin(Visitor v) {
    try {
      AccessManager accessMgr = AccessManager.instance();
      List orgAdmins = accessMgr.getOwnerObjectsForPrincipal((Principal)v, ORGANIZATION_ADMIN);
      if ((null != orgAdmins) && (orgAdmins.size() > 0)) {
        return true;
      }
    }
    catch (Exception ex) {
    }
    return false;
  }

  public void reset() {
    setPassword("");
    setConfirmPassword("");
    setUserAlias("");
    setFirstName("");
    setMiddleName("");
    setLastName("");
    setFullName("");
    setAddress1("");
    setAddress2("");
    setMailStop("");
    setCity("");
    setState("");
    setZipCode("");
    setCountry("");
    setPhone("");
    setFax("");
    setEmail("");
    setEmailAlert(false);
    setInboxAlert(false);
    setIsPmOnly(true);
    setKmUserDeleted(false);
    //setUserTemplateId(0);
    //setKmEmailAlert(false);
  }     
    
  public long getUserId() {
    return userId;
  }

  public void setUserId(long userId) {
    this.userId = userId;
  }
          
  public String getUserAlias() {
    return userAlias;
  }
  
  public void setUserAlias(String userAlias) {
    this.userAlias = userAlias;
  }

  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  public String getThePassword() {
    return password;
  }

  public void setThePassword(String password) {
    this.password = password;
  }

  public String getConfirmPassword() {
    return confirmPassword;
  }
  public void setConfirmPassword(String confirmPassword) {
    this.confirmPassword = confirmPassword;
  }

  public String getFirstName() {
    return firstName;
  }
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getMiddleName() {
    return middleName;
  }
  public void setMiddleName(String middleName) {
    this.middleName = middleName;
  }

  public String getLastName() {
    return lastName;
  }
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  public String getFullName() {
    return fullName;
  }
  public void setFullName(String fullName) {
    this.fullName = fullName;
  }

  public String getAddress1() {
    return address1;
  }
  public void setAddress1(String address1) {
    this.address1 = address1;
  }

  public String getAddress2() {
    return address2;
  }
  public void setAddress2(String address2) {
    this.address2 = address2;
  }

  public String getMailStop() {
    return mailStop;
  }
  public void setMailStop(String mailStop) {
    this.mailStop = mailStop;
  }

  public String getCity() {
    return city;
  }
  public void setCity(String city) {
    this.city = city;
  }

  public String getState() {
    return state;
  }
  public void setState(String state) {
    this.state = state;
  }

  public String getZipCode() {
    return zipCode;
  }
  public void setZipCode(String zipCode) {
    this.zipCode = zipCode;
  }

  public String getCountry() {
    return country;
  }
  public void setCountry(String country) {
    this.country = country;
  }

  public String getPhone() {
    return phone;
  }
  public void setPhone(String phone) {
    this.phone = phone;
  }
   
  public String getFax() {
    return fax;
  }
  public void setFax(String fax) {
    this.fax = fax;
  }

  public String getEmail() {
    return email;
  }
  public void setEmail(String email) {
    this.email = email;
  }

  public String[] getAssignedRoles() {
    return assignedRoles;
  }
  public void setAssignedRoles(String[] assignedRoles) {
    this.assignedRoles = assignedRoles;
  }

  public String[] getGroupFQNs() {
    return groupFQNs;
  }
  public void setGroupFQNs(String[] newGroupFQNs) {
    this.groupFQNs = newGroupFQNs;
  }

  public boolean getCanEditRole() {
    return canEditRole;
  }
  public void setCanEditRole(boolean canEditRole) {
    this.canEditRole = canEditRole;
  }

  public boolean getEmailAlert() {
    return emailAlert;
  }
  public void setEmailAlert(boolean emailAlert) {
    this.emailAlert = emailAlert;
  }

  public boolean getInboxAlert() {
    return inboxAlert;
  }
  public void setInboxAlert(boolean inboxAlert) {
    this.inboxAlert = inboxAlert;
  }

  public boolean getIsPmOnly() {
    return isPmOnly;
  }
  public void setIsPmOnly(boolean isPmOnly) {
    this.isPmOnly = isPmOnly;
  }

  public boolean getKmEmailAlert() {
    return kmEmailAlert;
  }
  public void setKmEmailAlert(boolean kmEmailAlert) {
    this.kmEmailAlert = kmEmailAlert;
  }

  public boolean getKmUserDeleted() {
    return kmUserDeleted;
  }
  public void setKmUserDeleted(boolean kmUserDeleted) {
    this.kmUserDeleted = kmUserDeleted;
  }

  public long getUserTemplateId() {
    return userTemplateId;
  }
  public void setUserTemplateId(long userTemplateId) {
    this.userTemplateId = userTemplateId;
  }

  public long getServiceId() {
    return serviceId;
  }
  public void setServiceId(long newServiceId) {
    this.serviceId = newServiceId;
  }

  public boolean getUpdateRole() {
    return this.updateRole;
  }
  public void setUpdateRole(boolean newUpdateRole) {
    this.updateRole = newUpdateRole;
  }

}

